<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Spectrum Viewer Test</title>
	<script src="../../_libs/raphael-min.2.0.1.js"></script>
	<script src="../../../src/kekule.js?locals=en,zh&language1=en_us&modules=chemWidget,spectroscopy&min=false"></script>
	<link rel="stylesheet" type="text/css" href="../../../src/widgets/themes/default/kekule.css" />
	<style>
		#spectrumViewer
		{
			width: 600px;
			height: 400px;
		}
		#molViewer
		{
				width: 600px;
				height: 300px;
		}
		#objInspector
		{
			width: 400px;
		}
    	#objInspector .K-ValueListEditor-KeyCell
		{
			width: 250px;
		}
		section
		{
        	border: 1px solid #ccc;
			margin: 0.5em;
			float: left;
		}
		input[type="number"], input[type="text"]
		{
			width: 6em;
		}
	</style>
	<script>
		var viewer, molViewer, objInspector;
		var initialConfigValues = {};
		var initialSpectrumViewConfigValues = {};

		function getSpectrumDisplayConfigs()
		{
			return viewer.getRenderConfigs().getSpectrumDisplayConfigs();
		}
		function getSpectrumViewConfigs()
		{
			return viewer.getDisplayerConfigs().getSpectrumViewConfigs();
		}

		function $(id)
		{
			return document.getElementById(id);
		}
		function getInputElemValue(elem)
		{
			var widget = Kekule.Widget.getWidgetOnElem(elem);
			if (widget)
				return widget.getValue();
			else
			{
				if (elem.getAttribute('type') === 'checkbox')
					return !!elem.checked;
				else if (elem.getAttribute('type') === 'number')
					return parseFloat(elem.value);
				else
					return elem.value;
			}
		}
		function setInputElemValue(elem, value)
		{
			var widget = Kekule.Widget.getWidgetOnElem(elem);
			if (widget)
				return widget.setValue(value);
			else
			{
				if (elem.getAttribute('type') === 'checkbox')
					elem.checked = !!value;
				else
					elem.value = value;
			}
		}
		function getAllConfigInputElems()
		{
			var rootElem = $('secController');
			var configInputElems = rootElem.querySelectorAll('[data-config-prop]');
			return configInputElems;
		}
		function getAllSpectrumViewConfigInputElems()
		{
			var rootElem = $('secController');
			var configInputElems = rootElem.querySelectorAll('[data-view-config-prop]');
			return configInputElems;
		}

		function showCodeSnippet(code, doRepaint)
		{
			var s = code;
			if (doRepaint)
				s += '\nviewer.repaint();';
			console.log(code);
		}

		function reactInputElemChange(e)
		{
			var elem = e.target;
			var widget = Kekule.Widget.getBelongedWidget(elem);
			if (widget)
			{
				elem = widget.getElement();
			}
			var value = getInputElemValue(elem);
			var configPropName = elem.getAttribute('data-config-prop');
			var spectrumViewConfigPropName = elem.getAttribute('data-view-config-prop');
			if (configPropName)
			{
				getSpectrumDisplayConfigs().setPropValue(configPropName, value);
				var quotedValue = (typeof(value) === 'string')? '\'' + value + '\'': value;
				var code = 'viewer.getRenderConfigs().getSpectrumDisplayConfigs().set' + configPropName.upperFirst() + '(' + quotedValue + ');';
				showCodeSnippet(code, true);
			}
			else if (spectrumViewConfigPropName)
			{
				var sSpectrumMode = elem.getAttribute('data-view-config-prop-mode');
				if (sSpectrumMode)
				{
					getSpectrumViewConfigs().setDataModeSpecifiedConfigValue(spectrumViewConfigPropName, value, parseInt(sSpectrumMode));
				}
				else
				{
					getSpectrumViewConfigs().setPropValue(spectrumViewConfigPropName, value);
				}
			}
			else if (elem.tagName.toLowerCase() === 'select')  // var unit, or active section selector
			{
				if (elem === $('selActiveSection'))
				{
					doReactSpectrumActiveSectionChange(elem);
				}
				else
					doReactSpectrumVarUnitChange(elem);
			}
			if (viewer.getChemObj())
				viewer.repaint();
		}

		function doReactSpectrumVarUnitChange(elem)
		{
			var varInfos = getSpectrumIndepAndDepVarInfos();
			var varDef;
			if (elem === $('selIndepUnit'))
				varDef = varInfos.independent && varInfos.independent.varDef;
			else if (elem === $('selDepUnit'))
				varDef = varInfos.dependent && varInfos.dependent.varDef;
			if (varDef)
			{
				var value = elem.value;
				varDef.setExternalUnit(value);
				var varSymbol = varDef.getSymbol();
				if (varSymbol)
				{
					var code = 'spectrum.getVariable(\'{0}\').setExternalUnit(\'{1}\');'.format(varSymbol, value);
					showCodeSnippet(code, true);
				}
			}
		}
		function doReactSpectrumActiveSectionChange(elem)
		{
			var spectrum = getSpectrum();
			if (spectrum)
			{
				var value = parseInt(elem.value);
				spectrum.setActiveDataSectionIndex(value);
				var code = 'spectrum.setActiveDataSectionIndex({0});'.format(value);
				showCodeSnippet(code, true);
			}
		}

		function getSpectrum()
		{
			var obj = viewer.getChemObj();
			if (obj instanceof Kekule.Spectroscopy.Spectrum)
				return obj;
			else if (obj.getChildCount && obj.getChildAt)  // a list object?
			{
				for (var i = 0, l = obj.getChildCount(); i < l; ++i)
				{
					var childObj = obj.getChildAt(i);
					if (childObj instanceof Kekule.Spectroscopy.Spectrum)
						return childObj;
				}
				return null;
			}
		}

		function getSpectrumIndepAndDepVarInfos()
		{
			var result = {};
			var spectrum = getSpectrum(); // viewer.getChemObj();
			if (spectrum)
			{
				var section = spectrum.getActiveDataSection();
				if (section)
				{
					result.independent = section.getLocalVarInfoOfDependency(Kekule.VarDependency.INDEPENDENT)[0];
					result.dependent = section.getLocalVarInfoOfDependency(Kekule.VarDependency.DEPENDENT)[0];
				}
			}
			return result;
		}
		function updateSelectElemItems(selElem, itemStrs, itemValues, currValue)
		{
			selElem.innerHTML = '';
			var items = Kekule.ArrayUtils.clone(itemStrs);
			var values = Kekule.ArrayUtils.clone(itemValues || itemStrs);
			if (currValue && values.indexOf(currValue) < 0)
			{
				values.unshift(currValue);
				items.unshift(currValue);
			}
			for (var i = 0, l = items.length; i < l; ++i)
			{
				var child = selElem.ownerDocument.createElement('option');
				child.value = values? values[i]: items[i];
				child.innerHTML = items[i];
				if (values[i] === currValue)
					child.selected = true;
				selElem.appendChild(child);
			}
		}
		function updateAvailableVarUnits()
		{
			var spectrum = getSpectrum(); //viewer.getChemObj();
			if (spectrum)
			{
				var varInfos = getSpectrumIndepAndDepVarInfos();
				if (varInfos.independent)
				{
					var unitSymbols = spectrum.getVarAvailableExternalUnitSymbols(varInfos.independent.varDef);
					var currSymbol = varInfos.independent.varDef.getExternalUnit() || varInfos.independent.varDef.getInternalUnit();
					updateSelectElemItems($('selIndepUnit'), unitSymbols, null, currSymbol);
				}
				if (varInfos.dependent)
				{
					var unitSymbols = spectrum.getVarAvailableExternalUnitSymbols(varInfos.dependent.varDef);
					var currSymbol = varInfos.dependent.varDef.getExternalUnit() || varInfos.dependent.varDef.getInternalUnit();
					updateSelectElemItems($('selDepUnit'), unitSymbols, null, currSymbol);
				}
			}
		}
		function updateSectionSelector()
		{
			var spectrum = getSpectrum();
			if (spectrum)
			{
				var sectionNames = [];
				var sectionIndexes = [];
				for (var i = 0, l = spectrum.getDataSectionCount(); i < l; ++i)
				{
					var sec = spectrum.getDataSectionAt(i);
					var name = sec.getName() || ('' + i);
					sectionIndexes.push(i);
					sectionNames.push(name);
				}
				updateSelectElemItems($('selActiveSection'), sectionNames, sectionIndexes, (spectrum.getActiveDataSectionIndex() || 0));
			}
		}

		function resetConfigInputElemValues()
		{
			var configInputElems = getAllConfigInputElems();

			configInputElems.forEach(function(elem) {
				var configPropName = elem.getAttribute('data-config-prop');
				var value = initialConfigValues[configPropName];
				setInputElemValue(elem, value);
			});

			//var spectrumViewConfigInputElems = getAllSpectrumViewConfigInputElems();

			if (viewer.getChemObj())
				viewer.repaint();
		}

		function initConfigValues(config, spectrumViewConfig)
		{
			if (!config)
				config = getSpectrumDisplayConfigs();
			if (!spectrumViewConfig)
				spectrumViewConfig = getSpectrumViewConfigs();

			var configInputElems = getAllConfigInputElems();
			configInputElems.forEach(function(elem){
				var configPropName = elem.getAttribute('data-config-prop');

				if (!configPropName)
				{
					console.warn('Config prop name not set', elem);
				}
				else // if (configPropName)
				{
					if (!config.getPropInfo(configPropName))
						console.warn('Config prop name not found', configPropName);
					else
					{
						var value = config.getPropValue(configPropName);
						initialConfigValues[configPropName] = value;
						setInputElemValue(elem, value);
					}
				}
			});

			var spectrumViewConfigInputElems = getAllSpectrumViewConfigInputElems();
			spectrumViewConfigInputElems.forEach(function(elem){
				var spectrumViewConfigPropName = elem.getAttribute('data-view-config-prop');
				if (!spectrumViewConfigPropName)
				{
					console.warn('Spectrum view config prop name not set', elem);
				}
				else
				{
					if (!spectrumViewConfig.getPropInfo(spectrumViewConfigPropName))
						console.warn('Spectrum view config prop name not found', spectrumViewConfigPropName);
					var sSpectrumDataMode = elem.getAttribute('data-view-config-prop-mode');
					var value;
					if (Kekule.ObjUtils.notUnset(sSpectrumDataMode))
					{
						value = spectrumViewConfig.getDataModeSpecifiedConfigValue(spectrumViewConfigPropName, parseInt(sSpectrumDataMode));
					}
					else
						value = spectrumViewConfig.getPropValue(spectrumViewConfigPropName);
					initialSpectrumViewConfigValues[spectrumViewConfigPropName] = spectrumViewConfig.getPropValue(spectrumViewConfigPropName);
					setInputElemValue(elem, value);
				}
			});
		}

		function init()
		{
			viewer = Kekule.Widget.getWidgetById('spectrumViewer');
			molViewer = Kekule.Widget.getWidgetById('molViewer');
			objInspector = Kekule.Widget.getWidgetById('objInspector');

			var iaConfigs = molViewer.getViewerConfigs().getInteractionConfigs();
			iaConfigs.setEnableBasicObjectHotTrack(true);
			iaConfigs.setEnableBasicObjectSelect(true);
			iaConfigs.setEnableBasicObjectMultiSelect(true);

			var connector = new Kekule.ChemWidget.SpectrumCorrelationConnector(viewer, molViewer);
			connector.on('assignmentsSelected', function(e){
				console.log('assignmentsSelected', e.assignmentDetails);
			});
			connector.on('assignmentsHotTracked', function(e){
				console.log('assignmentsHotTracked', e.assignmentDetails);
			});

			viewer.on('load', function(e){
				var chemObj = viewer.getChemObj();
				objInspector.setObjects(getSpectrum());
				updateAvailableVarUnits();
				updateSectionSelector();
			});

			viewer.on('hoverOnSpectrumData', function(e){
				/*
				if (e.dataItem)
					console.log('Hover on data item', e.dataItem);
				*/
			});
			viewer.on('spectrumDataSelectionChange', function(e){
				//console.log('SpectrumDataSelectionChange', e, e.dataItems);
			});

			objInspector.on('propertyChange', function(e){
				viewer.repaint();
			});

			Kekule.X.Event.addListener($('formController'), 'change', reactInputElemChange);
			Kekule.X.Event.addListener($('btnResetValues'), 'click', resetConfigInputElemValues);

			initConfigValues();
		}
		Kekule.X.domReady(init);
	</script>
</head>
<body>
	<section id="secDisplayer">
		<div id="spectrumViewer" data-widget="Kekule.ChemWidget.Viewer"
				 data-chem-obj1="" data-autofit="true" data-predefined-setting="fullFunc" data-resizable="true"></div>
		<br />
		<div id="molViewer" data-widget="Kekule.ChemWidget.Viewer"
				 data-chem-obj1="" data-autofit="true" data-predefined-setting="fullFunc" data-resizable="true"></div>
	</section>
	<section id="secController">
		<form id="formController" action="#" onsubmit="javascript:void();">
			<fieldset>
				<legend>Spectrum</legend>
				<label>Active section: <select id="selActiveSection"></select></label>
				<br />
				<label>Independent variable unit: <select id="selIndepUnit"></select></label>
				<label>Dependent variable unit: <select id="selDepUnit"></select></label>
				<div>(Continuous spectrum)</div>
				<div style="margin-left: 2em">
					<label>Visible independent data range ratio from: </label><input id="inputVisibleIndepDataRangeFromContinuous" data-config-prop="visibleIndependentDataRangeFrom_Continuous" type="number" step="0.05" />
					<label>to: </label><input id="inputVisibleIndepDataRangeToContinuous" data-config-prop="visibleIndependentDataRangeTo_Continuous" type="number"  step="0.05" />
					<br />
					<label>Visible dependent data range ratio from: </label><input id="inputVisibleDepDataRangeFromContinuous" data-config-prop="visibleDependentDataRangeFrom_Continuous" type="number" step="0.05" />
					<label>to: </label><input id="inputVisibleDepDataRangeToContinuous" data-config-prop="visibleDependentDataRangeTo_Continuous" type="number" step="0.05" />
				</div>
				<div>(Peak spectrum)</div>
				<div style="margin-left: 2em">
					<label>Visible independent data range ratio from: </label><input id="inputVisibleIndepDataRangeFromPeak" data-config-prop="visibleIndependentDataRangeFrom_Peak" type="number" step="0.05" />
					<label>to: </label><input id="inputVisibleIndepDataRangeToPeak" data-config-prop="visibleIndependentDataRangeTo_Peak" type="number"  step="0.05" />
					<br />
					<label>Visible dependent data range ratio from: </label><input id="inputVisibleDepDataRangeFromPeak" data-config-prop="visibleDependentDataRangeFrom_Peak" type="number" step="0.05" />
					<label>to: </label><input id="inputVisibleDepDataRangeToPeak" data-config-prop="visibleDependentDataRangeTo_Peak" type="number" step="0.05" />
				</div>
			</fieldset>
			<fieldset>
				<legend>Data render</legend>
				<label>Data color: </label><input id="inputDataColor" data-config-prop="dataColor" type="color"></input>
				<br />
				<label>Data stroke width ratio: </label><input id="inputDataStrokeWidthRatio" data-config-prop="dataStrokeWidthRatio" type="number" step="0.025" />
				<label>min: </label><input id="inputDataStrokeWidthMin" data-config-prop="dataStrokeWidthMin" type="number" step="0.5" />
				<label>max: </label><input id="inputDataStrokeWidthMax" data-config-prop="dataStrokeWidthMax" type="number" step="0.5" />
				<label>fixed: </label><input id="inputDataStrokeWidthFixed" data-config-prop="dataStrokeWidthFixed" type="number" step="0.5" />
			</fieldset>
			<fieldset>
				<legend>Axis render</legend>
				<fieldset>
					<legend>General</legend>
					<label>Reverse axises</label><input id="inputReverseAxises" data-config-prop="reversedAxises" type="checkbox" />
					<label>Axis color: </label><input id="inputAxisColor" type="color" data-config-prop="axisColor"></input>
					<br />
					<label>Axis width ratio: </label><input id="inputAxisWidthRatio" data-config-prop="axisWidthRatio" type="number" step="0.025" />
					<label>min: </label><input id="inputAxisWidthMin" data-config-prop="axisWidthMin" type="number" step="0.5" />
					<label>max: </label><input id="inputAxisWidthMax" data-config-prop="axisWidthMax" type="number" step="0.5" />
					<label>fixed: </label><input id="inputAxisWidthFixed" data-config-prop="axisWidthFixed" type="number" step="0.5" />
					<br />
					<label>Axis scale mark size ratio: </label><input id="inputScaleSizeRatio" data-config-prop="axisScaleMarkSizeRatio" type="number" step="0.05" />
					<label>min: </label><input id="inputScaleSizeMin" data-config-prop="axisScaleMarkSizeMin" type="number" step="0.5" />
					<label>max: </label><input id="inputScaleSizeMax" data-config-prop="axisScaleMarkSizeMax" type="number" step="0.5" />
					<label>Unlabeled ratio: </label><input id="inputUnlabeledScaleSizeRatio" data-config-prop="axisUnlabeledScaleSizeRatio" type="number" step="0.05" />
					<br />
					<label>Scale mark preferred count: </label><input id="inputScaleMarkPreferredCount" data-config-prop="axisScaleMarkPreferredCount" type="number" />
					<br />
					<label>Axis label font family: </label><input id="inputAxisLabelFontFamily" data-config-prop="axisLabelFontFamily" type="text" />
					<label>Axis label font size: </label><input id="inputAxisLabelFontSize" data-config-prop="axisLabelFontSize" type="number" />
					<br />
					<label>Axis label color: </label><input id="inputAxisLabelFontColor" type="color" data-config-prop="axisLabelColor" ></input>
					<br />
					<label>Scale label font family: </label><input id="inputScaleLabelFontFamily" data-config-prop="axisScaleLabelFontFamily" type="text" />
					<label>Scale label font size: </label><input id="inputScaleLabelFontSize" data-config-prop="axisScaleLabelFontSize" type="number" />
					<br />
					<label>Scale label color: </label><input type="color" id="inputScaleLabelFontColor" data-config-prop="axisScaleLabelColor" ></input>
					<br />
					<label>Axis label padding ratio: </label><input id="inputAxisLabelPaddingRatio" data-config-prop="axisLabelPaddingRatio" type="number" step="0.025" />
					<label>Axis scale label padding ratio: </label><input id="inputAxisScaleLabelPaddingRatio" data-config-prop="axisScaleLabelPaddingRatio" type="number" step="0.025" />
				</fieldset>
				<br />
				<fieldset>
					<legend>Independent axis</legend>
					<label>Display axis</label><input id="inputDisplayIndepAxis" data-config-prop="displayIndependentAxis" type="checkbox" />
					<label>Reversed data direction</label><input id="inputReversedIndepDataDir" data-config-prop="reverseIndependentDataDirection" type="checkbox" />
					<label>Reversed axis align</label><input id="inputReversedIndepAxisAlign" data-config-prop="reverseIndependentAxisAlign" type="checkbox" />
					<br />
					<label>Display scales</label><input id="inputDisplayIndepAxisScales" data-config-prop="displayIndependentAxisScales" type="checkbox" />
					<label>Display label</label><input id="inputDisplayIndepAxisLabel" data-config-prop="displayIndependentAxisLabel" type="checkbox" />
					<label>Display unit</label><input id="inputDisplayIndepAxisUnit" data-config-prop="displayIndependentAxisUnit" type="checkbox" />
				</fieldset>
				<fieldset>
					<legend>Dependent axis</legend>
					<label>Display axis</label><input id="inputDisplayDepAxis" data-config-prop="displayDependentAxis" type="checkbox" />
					<label>Reversed data direction</label><input id="inputReversedDepDataDir" data-config-prop="reverseDependentDataDirection" type="checkbox" />
					<label>Reversed axis align</label><input id="inputReversedDepAxisAlign" data-config-prop="reverseDependentAxisAlign" type="checkbox" />
					<br />
					<label>Display scales</label><input id="inputDisplayDepAxisScales" data-config-prop="displayDependentAxisScales" type="checkbox" />
					<label>Display label</label><input id="inputDisplayDepAxisLabel" data-config-prop="displayDependentAxisLabel" type="checkbox" />
					<label>Display unit</label><input id="inputDisplayDepAxisUnit" data-config-prop="displayDependentAxisUnit" type="checkbox" />
				</fieldset>
			</fieldset>
			<fieldset>
				<legend>Spectrum View Interactions</legend>
				<label>Enable data hot track</label>
					<label><input id="inputEnableDataHotTrackOnContinuous" data-view-config-prop="enableSpectrumDataHotTrackOnMode" data-view-config-prop-mode="1" type="checkbox" />in continuous</label>
					<label><input id="inputEnableDataHotTrackOnPeak" data-view-config-prop="enableSpectrumDataHotTrackOnMode" data-view-config-prop-mode="2" type="checkbox" />in peak spectrum</label>
				<br />
				<label>Enable data select</label>
					<label><input id="inputEnableDataSelectOnContinuous" data-view-config-prop="enableSpectrumDataSelectOnMode" data-view-config-prop-mode="1" type="checkbox" />in continuous</label>
					<label><input id="inputEnableDataSelectOnPeak" data-view-config-prop="enableSpectrumDataSelectOnMode" data-view-config-prop-mode="2" type="checkbox" />in peak spectrum</label>
				<br />
				<label>Enable multi-select</label>
					<label><input id="inputEnableDataMultiSelectOnContinuous" data-view-config-prop="enableSpectrumDataMultiSelectOnMode" data-view-config-prop-mode="1" type="checkbox" />in continuous</label>
					<label><input id="inputEnableDataMultiSelectOnPeak" data-view-config-prop="enableSpectrumDataMultiSelectOnMode" data-view-config-prop-mode="2" type="checkbox" />in peak spectrum</label>
			</fieldset>
			<button id="btnResetValues" type="button">Reset values</button>
		</form>
	</section>
	<section id="secObjInspector">
		<div id="objInspector" data-widget="Kekule.Widget.ObjectInspector"></div>
	</section>
</body>
</html>